package com.groupbuying.gateway.filter;

import com.groupbuying.gateway.constants.CommonConstants;
import com.groupbuying.gateway.utils.JSONUtils;
import com.groupbuying.gateway.utils.JwtUtils;
import com.groupbuying.gateway.utils.R;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import org.springframework.beans.factory.annotation.Value;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Set;

/**
 * @author ywxd
 * @version V1.0
 * @des 过滤器
 */
public class AccessFilter extends ZuulFilter {

    private static String separator = ",";

    //过滤url
    @Value("${gateway_ignorePath:}")
    private String ignorePath;

    @Value("${gateway_ignoreEndPath:}")
    private String ignoreEndPath;

    @Override
    public String filterType() {
        return "pre";
    }

    @Override
    public int filterOrder() {
        return 10000;
    }

    @Override
    public boolean shouldFilter() {
        return true;
    }

    @Override
    public Object run() {
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest request = ctx.getRequest();
        final String requestUri = request.getRequestURI();

        //请求开始，记录开始时间
        request.setAttribute(CommonConstants.YDSTART_TIME,new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date()));
        request.setAttribute(CommonConstants.YDSTART_MILL,System.currentTimeMillis());
        request.setAttribute(CommonConstants.ORIGINAL_ADDRESS,requestUri);

        if (isStartWith(requestUri)) {
            return null;
        }

        if (isEndWith(requestUri)) {
            return null;
        }

        String accessToken = request.getHeader(CommonConstants.CONTEXT_TOKEN);
        if (null == accessToken || accessToken == "") {
            accessToken = request.getParameter(CommonConstants.TOKEN);
        }

        if (null == accessToken) {
            setFailedRequest(R.error401(), 200);
            return null;
        }

        try {
            //校验
            JwtUtils.getInfoFromToken(accessToken);
        } catch (Exception e) {
            setFailedRequest(R.error401(), 200);
            return null;
        }

        //鉴权
        if (!havePermission(request)) {
            setFailedRequest(R.error403(), 200);
            return null;
        }

        Set<String> headers = (Set<String>) ctx.get("ignoredHeaders");
        //We need our JWT tokens relayed to resource servers
        //添加自己header
        //ctx.addZuulRequestHeader(CommonConstants.CONTEXT_TOKEN, accessToken);
        //移除忽略token
        headers.remove("authorization");
        return null;
//        RequestContext ctx = RequestContext.getCurrentContext();
//        Set<String> headers = (Set<String>) ctx.get("ignoredHeaders");
//        // We need our JWT tokens relayed to resource servers
//        headers.remove("authorization");
//        return null;
    }

    private void setFailedRequest(Object body, int code) {
        RequestContext ctx = RequestContext.getCurrentContext();
        ctx.setResponseStatusCode(code);
        HttpServletResponse response = ctx.getResponse();
        PrintWriter out = null;
        try {
            out = response.getWriter();
            out.write(JSONUtils.beanToJson(body));
            out.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }
        ctx.setSendZuulResponse(false);
    }

    private boolean havePermission(HttpServletRequest request) {
        //TODO:菜单鉴权关闭
//        String currentURL = request.getRequestURI();
//        List<MenuDTO> menuDTOS = menuService.userMenus();
//        for (MenuDTO menuDTO : menuDTOS) {
//            if (currentURL != null && null != menuDTO.getUrl() && currentURL.startsWith(menuDTO.getUrl())) {
//                return true;
//            }
//        }
//        return false;
        return true;
    }

    private boolean isStartWith(String requestUri) {
        boolean flag = false;
        for (String s : ignorePath.split(separator)) {

            if (requestUri.startsWith(s)) {
                return true;
            }
        }
        return flag;
    }

    private boolean isEndWith(String requestUri) {
        boolean flag = false;
        for (String s : ignoreEndPath.split(separator)) {

            if (requestUri.endsWith(s)) {
                return true;
            }
        }
        return flag;
    }
}
